package com.quanquan.parking.etcp;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.quanquan.parking.etcp.response.*;
import com.quanquan.parking.utils.DecriptUtils;
import com.quanquan.parking.utils.Request;
import com.quanquan.parking.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @description:
 * @author:lihonglinag
 * @date:2019-04-02 15:53
 * @version:v 1.0.0
 */
@Component
@Slf4j
public class ParkProxy {

    private static final String PARK_TOKEN = "_park_token";
    private final static SimpleDateFormat timeStampSdf = new SimpleDateFormat("yyyyMMddHHmmss");
    private final StringRedisTemplate redisTemplate;

    @Value("${parking-params.base_url}")
    private  String baseUrl;

    @Value("${parking-params.merchant_key}")
    private  String merchantKey;

    @Value("${parking-params.secret}")
    private  String secret;

    @Value("${parking-params.park_id}")
    private  String parkId;

    @Value("${parking-params.bussness_id}")
    private  String bussnessId;

    @Autowired
    public ParkProxy(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /*public static void main(String[] are) {
        ParkProxy parkProxy = new ParkProxy();
        parkProxy.bindcar("苏A00001", "15203997213");
        // System.out.println(token);
    }*/

    /**
     * 获取用户token
     *
     * @param mobile
     * @return
     */
    public String getToken(String mobile) {
        String key = mobile + PARK_TOKEN;
        String token = null;
        //查redis中是否有此token
        if (redisTemplate.hasKey(key)) {
            token = redisTemplate.opsForValue().get(key);
            return token;
        }
        //无则新建
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/usersigin").toString();
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("mobilePhone", mobile);
        dataMap.put("appId", Config.APP_ID);
        DataResponse response = sendPost(url, dataMap, UsersiginResponse.class);
        System.out.println(response);
        if (null == response) {
            log.error("获取token失败");
            return null;
        }
        if (response.getCode() == 0) {
            UsersiginResponse usersiginResponse = (UsersiginResponse) response.getData();
            redisTemplate.opsForValue().set(mobile + PARK_TOKEN, usersiginResponse.getToken(), 20, TimeUnit.MINUTES);
            token = usersiginResponse.getToken();
        }
        return token;
    }

    /**
     * 获取签名
     *
     * @param data
     * @param merchantKey
     * @param timeStamp
     * @return
     */
    private String getSign(String data, String merchantKey, String timeStamp) {
        StringBuffer strBuffer = new StringBuffer().append(data).append(merchantKey).append(timeStamp);
        String md5 = DecriptUtils.md5(strBuffer.toString());
        return md5.toUpperCase();
    }

    /**
     * 用户绑定车牌
     *
     * @param plateNumber
     * @param mobile
     * @return
     */
    public DataResponse bindCar(String plateNumber, String mobile) {
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/bindcar").toString();
        Map<String, String> dataMap = new HashMap<>();
        String token = getToken(mobile);
        dataMap.put("token", token);
        dataMap.put("plateNumber", plateNumber);
        return sendPost(url, dataMap, String.class);
    }

    /**
     * 用户解绑车牌
     *
     * @param plateNumber
     * @param mobile
     * @return
     */
    public String untyingCar(String plateNumber, String mobile) {
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/unbindcar").toString();
        Map<String, String> dataMap = new HashMap<>();
        String token = getToken(mobile);
        dataMap.put("token", token);
        dataMap.put("plateNumber", plateNumber);
        DataResponse response = sendPost(url, dataMap, String.class);
        if (null == response) {
            return null;
        }
        if (response.getCode() == 0) {
            return (String) response.getMessage();
        } else {
            return (String) response.getMessage();
        }
    }

    /**
     * 已绑车辆信息查询
     *
     * @param mobile
     * @return
     */
    public CarNumResponse carnum(String mobile) {
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/carnum").toString();
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("token", getToken(mobile));
        return sendGetRequest(url, dataMap, CarNumResponse.class);
    }

    /**
     * 查看停车场状态
     *
     * @return
     */
    public ParkingResponse parkingStatus() {
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/parkingstatus").toString();
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("parkingId", parkId);
        return sendPostRequest(url, dataMap, ParkingResponse.class);
    }


    /**
     * 商家优免券列表
     *
     * @return
     */
    public List<CouponResponse> couponList() throws UnsupportedEncodingException {
      /*  String MDParkId = new String(Base64.encodeBase64String(Config.PARK_ID.getBytes("UTF-8")));
        String MDBusinessId = new String(Base64.encodeBase64String(Config.BUSSNESS_ID.getBytes("UTF-8")));*/
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/b/coupon/list").toString();
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("parkId", parkId);
        dataMap.put("businessId", bussnessId);
        return sendPostArrayRequest(url, dataMap, CouponResponse.class);
    }

    /**
     * 商家优免券发放
     *
     * @param carNumber
     * @param couponFreeId 优免券模板id ETCP
     * @return
     */
    public String record(String carNumber, String couponFreeId) throws UnsupportedEncodingException {
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/b/coupon/record").toString();
        Map<String, String> dataMap = new HashMap<>();
        /*String MDParkId = new String(Base64.encodeBase64String(Config.PARK_ID.getBytes("UTF-8")));
        String MDBusinessId = new String(Base64.encodeBase64String(Config.APP_ID.getBytes("UTF-8")));*/
        dataMap.put("parkId", parkId);
        dataMap.put("businessId", bussnessId);
        dataMap.put("vehicleNo", carNumber);
        dataMap.put("couponFreeId", couponFreeId);
        String msg = sendPostRequest(url, dataMap, String.class);
        return msg;
    }

    /**
     * 车辆进出场模拟
     *
     * @param plateNumber
     * @return
     */
    public SimulationResponse simulation(String plateNumber) {
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/car/simulation").toString();
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("appId", Config.APP_ID);
        dataMap.put("plateNumber", plateNumber);
        SimulationResponse simulationResponse = sendPostRequest(url, dataMap, SimulationResponse.class);
        return simulationResponse;
    }

    /**
     * 查询停车费
     *
     * @param plateNumber
     * @param mobile
     * @return
     */
    public DataResponse orderRunPay(String plateNumber, String mobile) {
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/orderunpay").toString();
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("token", getToken(mobile));
        dataMap.put("plateNumber", plateNumber);
        dataMap.put("appId", Config.APP_ID);
        System.out.println(dataMap);
       // List<OrderResponse> orderResponse = sendGetArrayRequest(url, dataMap, OrderResponse.class);
        DataResponse dataResponse = sendGetRequest1(url, dataMap, OrderResponse.class);
        return dataResponse;
    }

    /**
     * 停车费支付
     *
     * @param mobile
     * @param orderId
     * @return
     */
    public DataResponse orderPay(String mobile, String orderId) {
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/orderpay").toString();
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("token", getToken(mobile));
        dataMap.put("payType", 1);
        dataMap.put("synId", orderId);
        dataMap.put("returnUrl", Config.RETURN_URL);
        System.out.println(dataMap);
        return sendPost(url, dataMap, OrderPayResponse.class);
    }


    /**
     * 停车记录
     *
     * @param mobile
     * @return
     */
    public List<OrderHistoryResponse> orderHistory(String mobile) {
        String url = new StringBuffer().append(baseUrl).append("/merchant/open/1.0.0/openapi/orderhistory").toString();
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("token", getToken(mobile));
        System.out.println(dataMap);
        return sendGetArrayRequest(url, dataMap, OrderHistoryResponse.class);
    }


    private DataResponse sendPost(String url, Object param, Class clazz) {
        String dataStr = JSON.toJSONString(param);
        String timeStamp = timeStampSdf.format(new Date());
        Map<String, Object> params = new HashMap<>();
        params.put("merchant_no", merchantKey);
        params.put("time_stamp", timeStamp);
        params.put("data", dataStr);
        params.put("sign", getSign(dataStr, secret, timeStamp));
        String result = Request.sendPost(url, params);
        if (StringUtils.isEmpty(result)) {
            return null;
        }
        DataResponse response = JSONObject.parseObject(result, DataResponse.class);
        if (null != response.getData()) {
            JSONObject dataObj = (JSONObject) response.getData();
            Object o = dataObj.toJavaObject(clazz);
            response.setData(o);
        }
        return response;
    }

    /**
     * 发送post请求，获得停车场返回值
     *
     * @param url
     * @param data
     * @return
     */

    private <T> T sendPostRequest(String url, Object data, Class<T> clazz) {
        String dataStr = JSON.toJSONString(data);
        String timeStamp = timeStampSdf.format(new Date());
        Map<String, Object> params = new HashMap<>();
        params.put("merchant_no", merchantKey);
        params.put("time_stamp", timeStamp);
        params.put("data", dataStr);
        params.put("sign", getSign(dataStr, secret, timeStamp));
        String result = Request.sendPost(url, params);
        if (StringUtils.isEmpty(result)) {
            return null;
        }
        JSONObject jsonObject = JSONObject.parseObject(result);

        if (jsonObject.containsKey("code")) {
            Integer code = jsonObject.getInteger("code");
            if (code == 0) {
                String resDataStr = jsonObject.getString("data");
                if (StringUtils.isNotEmpty(resDataStr)) {
                    return JSON.parseObject(resDataStr, clazz);
                } else {
                    String resData = "1";
                    return JSON.parseObject(resData, clazz);
                }
            }
        }
        return null;
    }

    /**
     * 发送post请求，获得停车场返回值,返回值为数组时使用
     *
     * @param url
     * @param data
     * @return
     */
    private <T> List<T> sendPostArrayRequest(String url, Object data, Class<T> clazz) {
        String dataStr = JSON.toJSONString(data);
        String timeStamp = timeStampSdf.format(new Date());
        Map<String, Object> params = new HashMap<>();
        params.put("merchant_no", merchantKey);
        params.put("time_stamp", timeStamp);
        params.put("data", dataStr);
        params.put("sign", getSign(dataStr, secret, timeStamp));
        String result = Request.sendPost(url, params);
        if (StringUtils.isEmpty(result)) {
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(result);
        System.out.println(jsonObject);
        if (jsonObject.containsKey("code")) {
            Integer code = jsonObject.getInteger("code");
            if (code == 0) {
                String resDataStr = jsonObject.getString("data");
                if (StringUtils.isNotEmpty(resDataStr)) {
                    return JSON.parseArray(resDataStr, clazz);
                }
            }
        }
        return null;
    }


    /**
     * 发送get请求，获得停车场返回值
     *
     * @param url
     * @param data
     * @return
     */
    private <T> T sendGetRequest(String url, Object data, Class<T> clazz) {
        String dataStr = JSON.toJSONString(data);
        String timeStamp = timeStampSdf.format(new Date());
        Map<String, Object> params = new HashMap<>();
        params.put("merchant_no", merchantKey);
        params.put("time_stamp", timeStamp);
        params.put("data", dataStr);
        params.put("sign", getSign(dataStr, secret, timeStamp));
        String result = Request.sendGet(url, params);
        if (StringUtils.isEmpty(result)) {
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(result);
        if (jsonObject.containsKey("code")) {
            Integer code = jsonObject.getInteger("code");
            if (code == 0) {
                String resDataStr = jsonObject.getString("data");
                if (StringUtils.isNotEmpty(resDataStr)) {
                    return JSON.parseObject(resDataStr, clazz);
                } else {
                    String resData = "1";
                    return JSON.parseObject(resData, clazz);
                }
            }
        }
        return null;
    }

    private DataResponse sendGetRequest1(String url, Object param, Class clazz) {
        String dataStr = JSON.toJSONString(param);
        String timeStamp = timeStampSdf.format(new Date());
        Map<String, Object> params = new HashMap<>();
        params.put("merchant_no", merchantKey);
        params.put("time_stamp", timeStamp);
        params.put("data", dataStr);
        params.put("sign", getSign(dataStr, secret, timeStamp));
        String result = Request.sendGet(url, params);
        if (StringUtils.isEmpty(result)) {
            return null;
        }
        DataResponse response = JSONObject.parseObject(result, DataResponse.class);
        if (null != response.getData()) {
            if (response.getData().toString().contains("[")){
                JSONArray array = (JSONArray) response.getData();
                JSONObject dataObj = (JSONObject) array.get(0);
                Object o = dataObj.toJavaObject(clazz);
                response.setData(o);
            }else {
                JSONObject dataObj = (JSONObject) response.getData();
                Object o = dataObj.toJavaObject(clazz);
                response.setData(o);
            }
        }
        return response;
    }

    /**
     * 发送post请求，获得停车场返回值,返回值为数组时使用
     *
     * @param url
     * @param data
     * @return
     */
    private <T> List<T> sendGetArrayRequest(String url, Object data, Class<T> clazz) {
        String dataStr = JSON.toJSONString(data);
        String timeStamp = timeStampSdf.format(new Date());
        Map<String, Object> params = new HashMap<>();
        params.put("merchant_no", merchantKey);
        params.put("time_stamp", timeStamp);
        params.put("data", dataStr);
        params.put("sign", getSign(dataStr, secret, timeStamp));
        String result = Request.sendGet(url, params);
        if (StringUtils.isEmpty(result)) {
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(result);
        System.out.println(jsonObject);
        if (jsonObject.containsKey("code")) {
            Integer code = jsonObject.getInteger("code");
            if (code == 0) {
                String resDataStr = jsonObject.getString("data");
                if (StringUtils.isNotEmpty(resDataStr)) {
                    return JSON.parseArray(resDataStr, clazz);
                }
            }
        }
        return null;
    }

}
